const DEFAULT_FOV = Math.PI / 6;
const HALF_PI = Math.PI / 2;

export default class MousePanCameraController {

  constructor(frame, speed, fov = DEFAULT_FOV) {
    this._deltaPitch = 0;
    this._deltaYaw = 0;
    this._speed = speed;
    this._verticalFov = fov;
    this._frame = frame;
    this._enabled = true
    this._mouseMoving = false;
    this._lastMouseX = 0;
    this._lastMouseY = 0;

    this._frame.addEventListener('mouseenter', this._onMouseEnter)
    this._frame.addEventListener('mouseleave', this._onMouseLeave)
    // this._frame.addEventListener('mousemove', this._onMouseMove)
  }

  _onMouseEnter = (e) => {
    // console.log('onMouseEnter')
    this._mouseMoving = true
    this.disable()
  }

  _onMouseMove = (e) => {
    if (this._mouseMoving) {
      const width = this._frame.clientWidth;
      const height = this._frame.clientHeight;
      const aspect = width / height;
      const deltaX = e.clientX - this._lastMouseX;
      const deltaY = e.clientY - this._lastMouseY;
      this._lastMouseX = e.clientX;
      this._lastMouseY = e.clientY;
      this._deltaPitch += deltaX / width * this._verticalFov * aspect;
      this._deltaYaw += deltaY / height * this._verticalFov;
      this._deltaYaw = Math.max(-HALF_PI, Math.min(HALF_PI, this._deltaYaw));
    }
  }

  _onMouseLeave = (e) => {
    // console.log('onMouseLeave')
    this._mouseMoving = false
    this.enable()
  }

  _move () {
    const width = this._frame.clientWidth;
    const height = this._frame.clientHeight;
    const aspect = width / height;
    // const deltaX = 0.5 //e.clientX - this._lastMouseX;
    const deltaX = this._speed //e.clientX - this._lastMouseX;
    const deltaY = 0 //e.clientY - this._lastMouseY;
    // this._lastMouseX = e.clientX;
    // this._lastMouseY = e.clientY;
    this._deltaPitch += deltaX / width * this._verticalFov * aspect;
    // this._deltaYaw += deltaY / height * this._verticalFov;
    // this._deltaYaw = Math.max(-HALF_PI, Math.min(HALF_PI, this._deltaYaw));
  }

  enable () {
    this._enabled = true;
  }

  disable () {
    this._enabled = false;
  }

  fillCameraProperties (position, rotation) {
    if (!this._enabled) {
      return false;
    }

    this._move()

    if (this._deltaPitch === 0 && this._deltaYaw === 0) {
      return false;
    }

    // premultiply the camera rotation by the horizontal (pitch) rotation,
    // then multiply by the vertical (yaw) rotation

    const cp = Math.cos(this._deltaPitch / 2);
    const sp = Math.sin(this._deltaPitch / 2);
    const cy = Math.cos(this._deltaYaw / 2);
    const sy = Math.sin(this._deltaYaw / 2);

    const x1 = rotation[0];
    const y1 = rotation[1];
    const z1 = rotation[2];
    const w1 = rotation[3];

    const x2 = cp * x1 + sp * z1;
    const y2 = cp * y1 + sp * w1;
    const z2 = cp * z1 - sp * x1;
    const w2 = cp * w1 - sp * y1;

    const x3 = w2 * sy + x2 * cy;
    const y3 = y2 * cy + z2 * sy;
    const z3 = -y2 * sy + z2 * cy;
    const w3 = w2 * cy - x2 * sy;

    rotation[0] = x3;
    rotation[1] = y3;
    rotation[2] = z3;
    rotation[3] = w3;

    this._deltaPitch = 0;
    this._deltaYaw = 0;
    return true;
  }
}
